﻿using System;
using System.IO;
using System.Text;
using ICSharpCode.SharpZipLib.Zip;
using LitJson;

public static class LuaUnzipHelper
{
    public static void StartUnzipJobSync(Stream zipContent, string releasePath, Action<float> progressCallBack = null)
    {
        ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage;

        if (Directory.Exists(releasePath) == false)
            Directory.CreateDirectory(releasePath);
        zipContent.Seek(0, SeekOrigin.Begin);
        using (var zipFile = new ZipFile(zipContent))
        {
            var totalUnzipCount = (int)zipFile.Count;
            if (totalUnzipCount == 0)
                return;
            //解压缩文件，替换更新
            zipContent.Seek(0, SeekOrigin.Begin);
            int sloveCnt = 0;
            using (ZipInputStream s = new ZipInputStream(zipContent))
            {
                ZipEntry ent = null;

                byte[] buffer = new byte[10240];

                while ((ent = s.GetNextEntry()) != null)
                {
                    bool next = false;
                    if (string.IsNullOrEmpty(ent.Name))
                    {
                        next = true;
                        //   continue;
                    }

                    string path = Path.Combine(releasePath, ent.Name);
                    if (string.IsNullOrEmpty(Path.GetFileName(path)))
                    {
                        next = true;
                        //   continue;
                    }
                    if (!next)
                    {
                        string dir = Path.GetDirectoryName(path);
                        if (Directory.Exists(dir) == false)
                        {
                            Directory.CreateDirectory(dir);
                        }

                        if (File.Exists(path))
                        {
                            File.Delete(path);
                        }

                        using (var stream = new FileStream(path, FileMode.OpenOrCreate))
                        {
                            while (true)
                            {
                                int size = s.Read(buffer, 0, buffer.Length);
                                if (size > 0)
                                    stream.Write(buffer, 0, size);
                                else
                                    break;
                            }

                            stream.Flush();
                        }
                    }
                    sloveCnt++;
                    if (progressCallBack != null)
                    {
                        progressCallBack(sloveCnt * 1.0f / totalUnzipCount);
                    }
                    AppFacade.eventManager.DispatchEvent(EventDef.UNZIP_PROGRESS, sloveCnt * 1.0f / totalUnzipCount);
                }
            }
        }
    }

    public static ThreadJob StartUnzipJob(Stream content, string releasePath, Action<float> progressCallBack = null)
    {
        if (Directory.Exists(releasePath) == false)
            Directory.CreateDirectory(releasePath);

        string[] remainFiles = Directory.GetFiles(releasePath);
        foreach (var fileName in remainFiles)
        {
            UnityEngine.Debug.Log(releasePath + " Delete Remain File: " + fileName);
            //File.Delete(fileName);
        }

        var extractAndVerifyJob = AppFacade.threadManager.SetJob(() =>
        {
            StartUnzipJobSync(content, releasePath, progressCallBack);
        });

        return extractAndVerifyJob;
    }

    public static ThreadJob StartUnzipThreadJob(byte[] zipContent, string releasePath, Action<float> progressCallBack = null)
    {
        var extractAndVerifyJob = AppFacade.threadManager.SetJob(() =>
        {
            StartUnzipJobSync(new MemoryStream(zipContent), releasePath, progressCallBack);
            string str = File.ReadAllText(Path.Combine(LoadManager.configPath, "MD5"));
            JsonData md5Json = JsonMapper.ToObject(str);
            int total = md5Json.Count;
            int cnt = 0;
            foreach (JsonData amd5Data in md5Json)
            {
                string name = (string)(amd5Data["name"]);
                string md5 = (string)(amd5Data["md5"]);
                string filePath = Path.Combine(LoadManager.configPath, name);
                if (File.Exists(filePath))
                {
                    using (var fs = new FileStream(filePath, FileMode.Open))
                    {                            
                        string localMd5 = MD5Helper.ComputeMD5(fs).ToLower();
                        
                        if (localMd5 != md5.ToLower())
                        {
                            throw(new Exception("config data Md5 error " + name + localMd5 + " " + md5));
                        }
                        cnt++;
                        AppFacade.eventManager.DispatchEvent(EventDef.CHECK_CONFIGMD5_PROGRESS, cnt * 1.0f / total);
                    }
                }
                else                       
                {
                    throw (new Exception("config data lost " + filePath));
                }
            }
        });
        return extractAndVerifyJob;
    }
}
